You can fill inn the MarkDown cells (the cells without "numbering") by double-clicking them. Also remember, press shift + enter
to execute a cell.
A couple of useful links:
For this to work, you will have to have a version of cellpy
satisfying the criteria in the paragraph above. You might have to do a pre-release install to get it or clone the github repository and install in developer-mode.
Installing a pre-release with pip.
pip install --upgrade --pre cellpy
(if this is the first time you install cellpy
, you can skip the --upgrade
option)
Installing after cloning using pip in developer-mode. Note that you have to be in the directory where you have put the cellpy package (where the setup.py file is), if not, using .
as argument will not work and you will have to provide the full path to the setup.py file):
pip install -e .
For cellpy
to find stuff, it needs to know where to look. A config file exists for this purpose. It is typically located in your home directory (for mac and linux) or in your documents directory (for Windows) and has a name on this form (replacing "username" with your real username):
.cellpy_prms_username.conf
The file format is YAML (be aware that it cares about white spaces). The most important settings for this notebook are probably the Paths. Make sure they make sense (and that both the paths and the db_path filename exist) and edit it if necessary.
Here is how a typical file (at least the top of it) looks like:
---
Paths:
cellpydatadir: cellpy_data/cellpyfiles
db_filename: cellpy_db.xlsx
db_path: cellpy_data/db
filelogdir: cellpy_data/logs
outdatadir: cellpy_data/out
rawdatadir: cellpy_data/raw
examplesdir: cellpy_data/examples
notebookdir: cellpy_data/notebooks
batchfiledir: cellpy_data/batchfiles
FileNames:
file_name_format: YYYYMMDD_[NAME]EEE_CC_TT_RR
Db:
db_type: simple_excel_reader
db_table_name: db_table
db_header_row: 0
db_unit_row: 1
db_data_start_row: 2
...
This notebook uses the cellpy
batch
utility. For it to work properly (or at all) you will have to provide it with a database. You can choose to implement a database and a loader your self. Currently, cellpy
ships with a very simple database solution that hardly justifies its name as a database. It reads an excel-file where the first row acts as column headers, the second provides the type (e.g. string, bool, etc), and the rest provides the necessary information for each of the cells (one row pr. cell).
A sample excel file ("db-file") is provided with this example. You will need fill inn values manually, one row for each cell you want to load. Then you will have to put it in the database folder (as defined in your config file where it says db_file:
in the Paths
-section). The name of the file must also be the same as defined in the config-file (db_filename:
, i.e cellpy_db.xlsx
in the example config file snippet above).
When cellpy
reads the file, it uses the batch column (see below) to select which rows (i.e. cells) to load. For example, if the "b01" batch column is the one you tell cellpy
to use and you provide it with the name "casandras_experiment", it will only select the rows that has "casandras_experiment" in the "b01" column. You provide cellpy
with the "lookup" name when you issue the batch.init
command, for example:
b = batch.init("casandras_experiment", "cool_project", batch_col="b01")
You must always have the columns colored green filled out. And make sure that the id
column (the first one in the example xlsx file) has a unique integer for each row (it is used as a "key" when looking up stuff from the file).
Make sure that the names of your experiment-files (for example your .res files) are on the form date_something_that_describes_the_cell.res
because this is the name-format supported at the moment (this is not strictly true, but just to be on the safe side...).
OK, thats all for now. Have a look at the source code in the github repository or
It is often helpful to formulate what you wanted to achieve with your experiment before actually going into depth of the data. I believe that it does not make you "biased" when processing your data, but instead sharpens your mind and motivates you to look more closely on your results. I might be wrong, off course. Then just skip filling in this part.
(State the main hypothesis for the current set of experiment)
(What do you expect to find out? What kind of tests did you perform?)
(State if there are any special considerations for this experiment)
In [ ]:
import numpy as np
import matplotlib.pyplot as plt
import cellpy
from cellpy import prms
from cellpy import prmreader
from cellpy.utils import batch
%matplotlib inline
In [ ]:
## Uncomment this and run for checking your cellpy parameters.
# prmreader.info()
In [ ]:
# Please fill in here
project = "xxx"
name = "xxx"
batch_col = "b01"
In [ ]:
print(" INITIALISATION OF BATCH ".center(80, "="))
b = batch.init(name, project, batch_col=batch_col)
In [ ]:
# setting some prms
b.experiment.export_raw = False
# b.experiment.export_cycles = True
# b.experiment.export_ica = True
In [ ]:
# load info from your db and write the journal pages
b.create_journal()
In [ ]:
# create the apropriate folders
b.paginate()
In [ ]:
# load the data (and save .csv-files if you have set export_(raw/cycles/ica) = True)
# (this might take some time)
b.update()
In [ ]:
# collect summary-data (e.g. charge capacity vs cycle number) from each cell and export to .csv-file(s).
b.combine_summaries()
In [ ]:
# Plot the charge capacity and the C.E. (and resistance) vs. cycle number (standard plot)
b.plot_summaries()
In [ ]:
# Show the journal pages
b.pages
In [ ]:
import hvplot.pandas
import holoviews as hv
In [ ]:
# hvplot does not like infinities
s = b.summaries.replace([np.inf, -np.inf], np.nan)
In [ ]:
layout = s["coulombic_efficiency"].hvplot() + s["discharge_capacity"].hvplot() * s["charge_capacity"].hvplot()
layout.cols(1)
In [ ]:
s["cumulated_coulombic_efficiency"].hvplot()
In [ ]:
discharge_capacity = b.summaries.discharge_capacity
charge_capacity = b.summaries.charge_capacity
coulombic_efficiency = b.summaries.coulombic_efficiency
ir_charge = b.summaries.ir_charge
In [ ]:
fig, (ax1, ax2) = plt.subplots(2, 1)
ax1.plot(discharge_capacity)
ax1.set_ylabel("capacity ")
ax2.plot(ir_charge)
ax2.set_xlabel("cycle")
ax2.set_ylabel("resistance")
In [ ]:
# Lets check what cells we have
cell_labels = b.experiment.cell_names
cell_labels
In [ ]:
# OK, then I choose one of them
label = cell_labels[0]
data = b.experiment.data[label]
In [ ]:
cap = data.get_cap(categorical_column=True)
cap.head()
In [ ]:
fig, ax = plt.subplots()
ax.plot(cap.capacity, cap.voltage)
ax.set_xlabel("capacity")
ax.set_ylabel("voltage")
In [ ]:
c4,v4 = data.get_cap(cycle=4, method="forth-and-forth")
c10,v10 = data.get_cap(cycle=10, method="forth-and-forth")
fig, ax = plt.subplots()
ax.set_xlabel("capacity")
ax.set_ylabel("voltage")
ax.plot(c4,v4, "ro", label="cycle 4")
ax.plot(c10,v10, "bs", label="cycle 22")
ax.legend();
In [ ]:
from cellpy.utils import ica
v4, dqdv4 = ica.dqdv_cycle(
data.get_cap(
4,
categorical_column=True,
method = "forth-and-forth")
)
v10, dqdv10 = ica.dqdv_cycle(
data.get_cap(
10,
categorical_column=True,
method = "forth-and-forth")
)
plt.plot(v4,dqdv4, label="cycle 4")
plt.plot(v10, dqdv10, label="cycle 10")
plt.legend();
In [ ]:
fig, ax = plt.subplots()
for cycle in data.get_cycle_numbers():
d = data.get_cap(
cycle,
categorical_column=True,
method = "forth-and-forth"
)
if not d.empty:
v, dqdv = ica.dqdv_cycle(d)
ax.plot(v, dqdv)
else:
print(f"cycle {cycle} seems to be missing or corrupted")
In [ ]:
hv.extension('bokeh')
In [ ]:
tidy_ica = ica.dqdv_frames(data)
cycles = list(range(1,3)) + [10, 15]
tidy_ica = tidy_ica.loc[tidy_ica.cycle.isin(cycles), :]
In [ ]:
%%opts Curve [xlim=(0,1)] NdOverlay [legend_position='right']
#legend_cols=True]
curve4 = (hv.Curve(tidy_ica, kdims=['voltage'], vdims=['dq', 'cycle'], label="Incremental capacity plot")
.groupby("cycle")
.opts(
style={"Curve": dict(color=hv.Palette("Viridis"))},
)
.overlay()
.opts(
width=800,
height=500,
)
)
curve4
In [ ]: